using System;
using System.Collections.Generic;
using System.Web.UI;
using PHSRAG.Insight21.Common.Filters;
using PHSRAG.Utility;
using PHSRAG.WebControls;

namespace PHSRAG.Insight21.Common.Pages
{
    /// <summary>
    /// This class is designed to act as a base for all Insight pages.
    /// The page supports client side
    /// dirty state management if desired.
    /// </summary>
    public class BasePage : Page
    {
        private bool _clientSideDirtyStateManagementEnabled;
        private List<String> _controlIdsToSkipDirtyChecks = new List<string>();
        private bool? _isSessionHeartbeatEnabled;

        #region Overrides

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event to initialize the page.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            PreRender += OnPagePreRender;
            base.OnInit(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Page.LoadComplete"/> event at the end of the page load stage.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnLoadComplete(EventArgs e)
        {
            if (ClientSideDirtyStateManagementEnabled)
            {
                ClientScript.RegisterClientScriptInclude("DirtyStateManagement", Page.ResolveUrl("~/Scripts/DirtyStateManagement.js"));
                ClientScript.RegisterStartupScript(GetType(), "DirtyStateManagement", "SetupDirtyStateManagement();", true);
                ClientScript.RegisterClientScriptBlock(GetType(), "ControlIdsToSkipDirtyChecks", string.Format("var controlIdsToSkipDirtyChecks = \"{0}\";", String.Join(",", ControlIdsToSkipDirtyChecks.ToArray())), true);
            }
            base.OnLoadComplete(e);
        }

        #endregion

        #region Page Event Handlers

        /// <summary>
        /// Called when page PreRender event is raised.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnPagePreRender(object sender, EventArgs e)
        {
            AddClientScripts();
        }

        #endregion

        #region Properties

        protected bool ClientSideDirtyStateManagementEnabled
        {
            get { return _clientSideDirtyStateManagementEnabled; }
            set { _clientSideDirtyStateManagementEnabled = value; }
        }

        protected List<String> ControlIdsToSkipDirtyChecks
        {
            get { return _controlIdsToSkipDirtyChecks; }
            set { _controlIdsToSkipDirtyChecks = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether session heartbeat is enabled.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if session heartbeat is enabled; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsSessionHeartbeatEnabled
        {
            get
            {
                if (_isSessionHeartbeatEnabled == null)
                {
                    return Settings.GetKeyValue("Session.Heartbeat.IsEnabled", false);
                }
                
                return (bool)_isSessionHeartbeatEnabled;
            }

            set { _isSessionHeartbeatEnabled = value; }
        }

        #endregion

        #region Exception Handling

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="annunciator">Reference to the annunciator where the message would be displayed.</param>
        /// <param name="ex">The exception to report on.</param>
        protected void DisplayExceptionReport(Annunciator annunciator, Exception ex)
        {
            DisplayExceptionReport(annunciator, ex, false);
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception and all
        /// inner exception messages. Also has the option to log the exception to the event viewer.
        /// </summary>
        /// <param name="annunciator">Reference to the annunciator where the message would be displayed.</param>
        /// <param name="ex">The exception to report on.</param>
        /// <param name="logToEventVwr"></param>
        protected void DisplayExceptionReport(Annunciator annunciator, Exception ex, bool logToEventVwr)
        {
            if (annunciator != null)
            {
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
            if (logToEventVwr)
            {
                ExceptionReport.WriteToEventLog(string.Empty, ex, true, ExceptionReport.ReportType.Error);
            }
        }

        /// <summary>
        /// Displays an error message on the screen to the user.
        /// </summary>
        /// <param name="annunciator">Reference to the annunciator where the message would be displayed.</param>
        /// <param name="message">The message to be displayed to the user.</param>
        protected void DisplayExceptionReport(Annunciator annunciator, string message)
        {
            if (annunciator != null)
            {
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = message;
            }
        }

        #endregion

        #region Client Scripts

        /// <summary>
        /// Adds client scripts and script file references.
        /// </summary>
        private void AddClientScripts()
        {
            HeadFilter filter = new HeadFilter(Response.Filter);

            // Add session heartbeat global variables
            if (IsSessionHeartbeatEnabled)
            {
                string jsCode =
                    "var AppRoot = '" + ResolveUrl("~/") + "'; " +
                    "var IsSessionHeartbeatEnabled = " + IsSessionHeartbeatEnabled.ToString().ToLower() + "; " +
                    "var SessionTimeoutMessage = '" + Settings.GetKeyValue("Session.TimeoutMessage", string.Empty) + "'; " +
                    "var SessionTimeoutMs = " + (Session.Timeout - 1) * 60000 + "; "; // session timeout in milliseconds (minus 1 minute buffer for page load)

                filter.AddLiteralText(string.Format("<script type=\"text/javascript\">{0}</script>", jsCode));
            }

            // jQuery reference
            filter.AddLiteralText(string.Format("<script type=\"text/javascript\" src=\"{0}Scripts/jquery.min.js\"></script>", ResolveUrl("~/")));

            // Add session heartbeat js file reference and initialization code
            if (IsSessionHeartbeatEnabled)
            {
                filter.AddLiteralText(string.Format("<script type=\"text/javascript\" src=\"{0}Scripts/SessionHeartbeat.js\"></script>", ResolveUrl("~/")));

                ClientScript.RegisterClientScriptBlock(GetType(), "SessionHeartbeatInit", "$(function(){ InitSessionHeartbeat(); });", true);
            }

            Response.Filter = filter;
        }

        #endregion
    }
}